package com.tl.satoken.task;

import com.tl.satoken.domain.entity.Player;
import com.tl.satoken.service.RoomService;
import com.tl.satoken.netty.WebSocketFrameHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Component
public class MouseSelectionTask {

    @Autowired
    private RoomService roomService;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private WebSocketFrameHandler webSocketFrameHandler;

    // 每一分钟执行一次

    @Scheduled(fixedRate = 60000)
    public void selectMouseForAllRooms() {
        try {
            log.info("开始执行金老鼠选择定时任务");

            // 1. 延迟40秒后执行持久化和广播游戏结束消息,40秒后后续工作早已执行完毕
            // 发送end之后一定要能看到coinCount
            scheduleGameEndBroadcast();
            
            // 2. 清除所有金币相关的Redis数据
            clearAllCoinData();
            
            // 3. 选择新的金老鼠
            List<String> allRoomIds = roomService.getAllRoomIds();
            if (allRoomIds.isEmpty()) {
                log.info("当前没有活跃房间，跳过金老鼠选择");
                return;
            }
            
            for (String roomId : allRoomIds) {
                selectMouseForRoom(roomId);
            }
            
            log.info("金老鼠选择定时任务执行完成，处理了 {} 个房间", allRoomIds.size());
        } catch (Exception e) {
            log.error("执行金老鼠选择定时任务失败", e);
        }
    }

    private void selectMouseForRoom(String roomId) {
        try {
            List<Player> players = roomService.getPlayersInRoom(roomId);
            if (players.isEmpty()) {
                log.debug("房间 {} 没有玩家，跳过金老鼠选择", roomId);
                return;
            }
            
            Integer currentMouse = roomService.getRoomMouse(roomId);
            if (currentMouse != null) {
                log.debug("房间 {} 已有金老鼠 {}，跳过选择", roomId, currentMouse);
                return;
            }
            
            Random random = new Random();
            Player selectedPlayer = players.get(random.nextInt(players.size()));
            
            boolean success = roomService.assignMouseToPlayer(roomId, selectedPlayer.getHeroId());
            if (success) {
                log.info("房间 {} 成功选择玩家 {} 为金老鼠", roomId, selectedPlayer.getHeroId());
                
                // 广播金老鼠选择消息给房间内所有玩家
                webSocketFrameHandler.broadcastCoinStartMessage(roomId, selectedPlayer.getHeroId());
            } else {
                log.warn("房间 {} 选择玩家 {} 为金老鼠失败", roomId, selectedPlayer.getHeroId());
            }
        } catch (Exception e) {
            log.error("为房间 {} 选择金老鼠失败", roomId, e);
        }
    }
    /**
     * 延迟40秒后执行持久化和广播游戏结束消息
     */
    private void scheduleGameEndBroadcast() {
        CompletableFuture.runAsync(() -> {
            try {
                Thread.sleep(40000); // 延迟40秒
                
                // 1. 处理金老鼠剩余金币 - 如果金老鼠还有剩余金币，归金老鼠所有
                roomService.handleMouseRemainingCoins();
                
                // 2. 计算所有玩家的金币总数  上一局的游戏数据
                Map<Integer, Integer> playerCoins = roomService.getAllPlayersCoinStats();
                log.info("计算完成，共有 {} 个玩家有金币", playerCoins.size());
                // 1. 持久化金币到用户表
                if (!playerCoins.isEmpty()) {
                    log.info("开始持久化金币到用户表");
                    roomService.persistAllPlayerCoins();
                    log.info("金币持久化完成");
                }
                
                // 2. 广播游戏结束消息
                log.info("开始广播游戏结束消息");
                webSocketFrameHandler.broadcastGameEndToAllPlayers(playerCoins);
                log.info("游戏结束消息广播完成");
            } catch (InterruptedException e) {
                log.error("延迟广播游戏结束消息被中断", e);
                Thread.currentThread().interrupt();
            } catch (Exception e) {
                log.error("延迟执行游戏结束相关操作失败", e);
            }
        });
    }

    /**
     * 清除所有金币相关的Redis数据并重置玩家金老鼠状态
     */
    public void clearAllCoinData() {
        try {
            log.info("开始清除所有金币相关的Redis数据");

            // 清除所有金币数据 (coin:*)
            Set<String> coinKeys = redisTemplate.keys("coin:*");
            if (coinKeys != null && !coinKeys.isEmpty()) {
                redisTemplate.delete(coinKeys);
                log.info("清除了 {} 个金币数据", coinKeys.size());
            }

            // 清除所有房间金币集合 (room:coins:*)
            Set<String> roomCoinsKeys = redisTemplate.keys("room:coins:*");
            if (roomCoinsKeys != null && !roomCoinsKeys.isEmpty()) {
                redisTemplate.delete(roomCoinsKeys);
                log.info("清除了 {} 个房间金币集合", roomCoinsKeys.size());
            }

            // 清除所有房间金币位置映射 (room:coin_position:*)
            Set<String> roomCoinPositionKeys = redisTemplate.keys("room:coin_position:*");
            if (roomCoinPositionKeys != null && !roomCoinPositionKeys.isEmpty()) {
                redisTemplate.delete(roomCoinPositionKeys);
                log.info("清除了 {} 个房间金币位置映射", roomCoinPositionKeys.size());
            }

            // 清除所有金老鼠金币数据 (game:mouse:*:coins)
            Set<String> mouseCoinKeys = redisTemplate.keys("game:mouse:*:coins");
            if (mouseCoinKeys != null && !mouseCoinKeys.isEmpty()) {
                redisTemplate.delete(mouseCoinKeys);
                log.info("清除了 {} 个金老鼠金币数据", mouseCoinKeys.size());
            }

            // 清除所有房间金老鼠标记 (game:room:*:mouse)
            Set<String> roomMouseKeys = redisTemplate.keys("game:room:*:mouse");
            if (roomMouseKeys != null && !roomMouseKeys.isEmpty()) {
                redisTemplate.delete(roomMouseKeys);
                log.info("清除了 {} 个房间金老鼠标记", roomMouseKeys.size());
            }

            // 清除所有房间冷却状态 (game:room:*:cooldown)
            Set<String> roomCooldownKeys = redisTemplate.keys("game:room:*:cooldown");
            if (roomCooldownKeys != null && !roomCooldownKeys.isEmpty()) {
                redisTemplate.delete(roomCooldownKeys);
                log.info("清除了 {} 个房间冷却状态", roomCooldownKeys.size());
            }

            // 清除所有玩家金老鼠金币抢取记录 (game:player:*:mouse_coins)
            Set<String> mouseCoinGrabKeys = redisTemplate.keys("game:player:*:mouse_coins");
            if (mouseCoinGrabKeys != null && !mouseCoinGrabKeys.isEmpty()) {
                redisTemplate.delete(mouseCoinGrabKeys);
                log.info("清除了 {} 个玩家金老鼠金币抢取记录", mouseCoinGrabKeys.size());
            }

            // 重置所有玩家的金老鼠状态
            resetAllPlayerMouseStatus();

            log.info("金币相关数据清除完成");
        } catch (Exception e) {
            log.error("清除金币相关数据失败", e);
        }
    }

    /**
     * 重置所有玩家的金老鼠状态为false
     */
    private void resetAllPlayerMouseStatus() {
        try {
            log.info("开始重置所有玩家的金老鼠状态");

            // 重置玩家数据中的isMouse字段 (game:player:*:data)
            Set<String> playerDataKeys = redisTemplate.keys("game:player:*:data");
            if (playerDataKeys != null && !playerDataKeys.isEmpty()) {
                int resetCount = 0;
                for (String playerDataKey : playerDataKeys) {
                    // 检查是否存在isMouse字段，如果存在则设置为false
                    if (Boolean.TRUE.equals(redisTemplate.opsForHash().hasKey(playerDataKey, "isMouse"))) {
                        redisTemplate.opsForHash().put(playerDataKey, "isMouse", false);
                        resetCount++;
                    }
                }
                log.info("重置了 {} 个玩家数据中的金老鼠状态", resetCount);
            }
            log.info("玩家金老鼠状态重置完成");
        } catch (Exception e) {
            log.error("重置玩家金老鼠状态失败", e);
        }
    }

}
